extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput, Meta, NestedMeta};

#[proc_macro_attribute]
pub fn endpoint_derive_for(attr: TokenStream, item: TokenStream) -> TokenStream {
    let input = parse_macro_input!(item as DeriveInput);
    let attr_args = parse_macro_input!(attr as syn::AttributeArgs);

    let mut derives = quote! {};

    for arg in attr_args {
        if let NestedMeta::Meta(Meta::NameValue(nv)) = arg {
            if nv.path.is_ident("usage") {
                if let syn::Lit::Str(ref lit_str) = nv.lit {
                    match lit_str.value().as_str() {
                        "response" => {
                            derives = quote! {
                                #[derive(Serialize, Deserialize, Clone, Debug, Default, ToSchema)]
                                #[serde(rename_all = "camelCase")]
                                #[serde(default)]
                            };
                        }
                        "query" => {
                            derives = quote! {
                                #[derive(Deserialize, Clone, Debug, Default, ToParameters, Validate)]
                                #[salvo(parameters(default_parameter_in = Query))]
                                #[serde(rename_all = "camelCase")]
                            };
                        }
                        "body" => {
                            derives = quote! {
                                #[derive(Serialize, Deserialize, Clone, Debug, Default, ToSchema, Validate)]
                                #[serde(rename_all = "camelCase")]
                                #[serde(default)]
                            };
                        }
                        _ => {}
                    }
                }
            }
        }
    }

    let output = quote! {
        #derives
        #input
    };

    output.into()
}
